/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.buss.core.utils;

import java.math.BigDecimal;
import java.util.Random;
import java.util.regex.Pattern;

/**
 * 
 * @author Administrator
 */
public class NumberUtil {

	// 默认除法运算精度,及即保留小数点多少位
	private static final int DEF_DIV_SCALE = 4;
	private static Pattern numberPatter = Pattern.compile("^[\\d\\.E\\,]*$");
	private static long Seed = System.currentTimeMillis();
	private static Random rand = new Random();

	public static boolean isNumber(String str) {
		return numberPatter.matcher(str).find();
	}

	public static boolean isInt(String str) {
		try {
			Integer.parseInt(str);
		} catch (NumberFormatException e) {
			return false;
		}
		return true;
	}

	public static boolean isInteger(String str) {
		return isInt(str);
	}

	public static boolean isLong(String str) {
		return true;
	}

	public static double round(double v, int scale) {
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, 4).doubleValue();
	}

	public static int getRandomInt(int max) {
		rand.setSeed(Seed);
		Seed += 1L;
		return rand.nextInt(max);
	}

	public static int toInt(byte[] bs) {
		return toInt(bs, 0);
	}

	public static int toInt(byte[] bs, int start) {
		int i = 0;
		i += ((bs[start] & 0xFF) << 24);
		i += ((bs[(start + 1)] & 0xFF) << 16);
		i += ((bs[(start + 2)] & 0xFF) << 8);
		i += (bs[(start + 3)] & 0xFF);
		return i;
	}

	public static byte[] toBytes(int i) {
		byte[] bs = new byte[4];
		bs[0] = (byte) (i >> 24);
		bs[1] = (byte) (i >> 16);
		bs[2] = (byte) (i >> 8);
		bs[3] = (byte) (i & 0xFF);
		return bs;
	}

	public static void toBytes(int i, byte[] bs, int start) {
		bs[start] = (byte) (i >> 24);
		bs[(start + 1)] = (byte) (i >> 16);
		bs[(start + 2)] = (byte) (i >> 8);
		bs[(start + 3)] = (byte) (i & 0xFF);
	}

	public static short toShort(byte[] bs) {
		return toShort(bs, 0);
	}

	public static short toShort(byte[] bs, int start) {
		short i = 0;
		i = (short) (i + ((bs[(start + 0)] & 0xFF) << 8));
		i = (short) (i + (bs[(start + 1)] & 0xFF));
		return i;
	}

	public static byte[] toBytes(short i) {
		byte[] bs = new byte[2];
		bs[0] = (byte) (i >> 8);
		bs[1] = (byte) (i & 0xFF);
		return bs;
	}

	public static void toBytes(short i, byte[] bs, int start) {
		bs[(start + 0)] = (byte) (i >> 8);
		bs[(start + 1)] = (byte) (i & 0xFF);
	}

	public static byte[] toBytes(long i) {
		byte[] bs = new byte[8];
		bs[0] = (byte) (int) (i >> 56);
		bs[1] = (byte) (int) (i >> 48);
		bs[2] = (byte) (int) (i >> 40);
		bs[3] = (byte) (int) (i >> 32);
		bs[4] = (byte) (int) (i >> 24);
		bs[5] = (byte) (int) (i >> 16);
		bs[6] = (byte) (int) (i >> 8);
		bs[7] = (byte) (int) (i & 0xFF);
		return bs;
	}

	public static void toBytes(long l, byte[] bs, int start) {
		byte[] arr = toBytes(l);
		for (int i = 0; i < 8; ++i) {
			bs[(start + i)] = arr[i];
		}
	}

	public static long toLong(byte[] bs) {
		return toLong(bs, 0);
	}

	public static long toLong(byte[] bs, int index) {
		return ((bs[index] & 0xFF) << 56 | (bs[(index + 1)] & 0xFF) << 48
				| (bs[(index + 2)] & 0xFF) << 40
				| (bs[(index + 3)] & 0xFF) << 32
				| (bs[(index + 4)] & 0xFF) << 24
				| (bs[(index + 5)] & 0xFF) << 16
				| (bs[(index + 6)] & 0xFF) << 8 | (bs[(index + 7)] & 0xFF) << 0);
	}

	/**
	 * 提供精确的加法运算。
	 * 
	 * @param v1
	 *            被加数
	 * @param v2
	 *            加数
	 * @return 两个参数的和
	 */
	public static double add(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return (b1.add(b2)).doubleValue();
	}

	/**
	 * 提供精确的减法运算。
	 * 
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @return 两个参数的差
	 */
	public static double sub(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return (b1.subtract(b2)).doubleValue();
	}

	/**
	 * 提供精确的乘法运算。
	 * 
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 */
	public static double mul(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return (b1.multiply(b2)).doubleValue();
	}

	/**
	 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后多少位，以后的数字四舍五入。
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @return 两个参数的商
	 */
	public static double div(double v1, double v2) {
		return div(v1, v2, DEF_DIV_SCALE);
	}

	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的商
	 */
	public static double div(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException(
					"The scale must be a positive integer or zero");
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return (b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP)).doubleValue();
	}

}
